#pragma once
#include "base/function.h"
#include "util/noncopyable.h"
#include "base/config.h"
#include "net/socket.h"

#include <atomic>
#include <string>
#include <vector>
namespace net_tools
{
  namespace util
  {
    class Count_down_cond;
  }
  class Eventloop;
  class Logthread;
  namespace net
  {
    class Accept;
    class Connect;
  } // namespace net
  namespace base
  {
    class Timeevent;
  } // namespace base
  class Eventloopthreadpool;
  class Tcpserver : net_tools::util::noncopyable
  {
  public:
    Tcpserver();
    ~Tcpserver(){};
    void Initserver(int thread_number = 0,
                    int work_thread_number = _C::WORK_THREAD_POOL_SIZE,
                    int mempool_block_number = _C::BUFFER_MEMPOOL_BLOCK_NUMBER,
                    int mempool_block_size = _C::BUFFER_MEMPOOL_BLOCK_SIZE,
                    std::string name = std::string("SERVER MAIN THREAD"));
    void Startserver(int port = _C::DEFAULT_PORT);
    int Get_connect_number();

    inline void Set_cpu_high_level_todo(func cb) { cpu_high_level_callback_ = std::move(cb); };
    inline void Set_before_loop_todo(eventloop_func cb) { before_loop_todo_ = std::move(cb); };

    inline void Set_connect_over_callback(connect_func cb) { connect_over_callback_ = std::move(cb); };
    void Add_timejob(const std::string job_name, func todo, timeval begin_time, timeval time, int count);
    void Add_timejob_after_sec(const std::string job_name, func todo, long int begin_after, long int sec, int count);
    void Del_timejob(const std::string job_name);
    net_tools::base::Timeevent *Add_once_timejob_at(func func_, timeval begin_time);
    net_tools::base::Timeevent *Add_once_timejob_after(func func_, timeval begin_time);
    net_tools::base::Timeevent *Add_once_timejob_after_sec(func func_, long int sec);
    bool Del_once_timejob(net_tools::base::Timeevent *timeevent);

  private:
    void New_connect(Eventloop *eventloop, sockaddr_in new_connect_addr, int new_connect_fd);
    void New_connect_call_back();

    static void Default_thread(Eventloop *eventloop, eventloop_func before_loop_todo, connect_func lose_callback, util::Count_down_cond *count_down_cond);

    static void Default_message(net::Connect *connect);
    static void Default_close(net::Connect *connect);
    static void Default_lose(net::Connect *connect);
    static void Default_user_close(net::Connect *connect);

    util::Count_down_cond *count_down_cond_;
    int thread_number_;
    std::vector<net_tools::Eventloop *> *eventlooppool_;
    Eventloopthreadpool *eventloopthreadpool_;
    Eventloop *eventloop_;
    net::Accept *accept_;
    int accept_fd;
    socklen_t sockaddr_in_size;
    static std::atomic<int> connect_number_;

    func cpu_high_level_callback_;
    eventloop_func before_loop_todo_;
    eventloop_func thread_todo;
    connect_func connect_over_callback_;

    connect_func message_callback_;
    connect_func close_callback_;
    connect_func lose_callback_;
  };

} // namespace net_tools